骨架屏真是个装逼神器
Start
为了更好地接入大型项目,这个章节我们准备接入React作为我们地前端框架,并且引入一个新鲜地概念——骨架屏,我们一起来看看这都是什么吧~
React
在配置webpack前,我们思考一下,我们需要哪些东西?
- 能转译jsx语法的babel
- 识别React语法的ESlint
- React相关依赖
只需要这些我们就能够完成React的简单配置
安装依赖
1 2
| npm install react react-dom npm install react babel-preset-react eslint-plugin-react -D
|
结合我们之前所学内容,从字面上来看就能够猜出他们都有哪些用处,这里就不一一介绍,如果不熟悉可以查阅我之前的博客。
配置webpack.config.js
React的代码都是写在.js文件当中,也就是babel去处理.js文件,上一节我们已经配置完了babel,所以我们只需要在.babelrc中添加babel对React的支持:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| { "presets": [ ["env", { "targets": { "browsers": ["last 2 versions", "safari >= 7"] }, "modules": "commonjs", "debug": true, "include": ["transform-es2015-arrow-functions"], "exclude": ["transform-es2015-for-of"] }], "react" ], "plugins": ["transform-runtime"] }
|
我们在presets中加上了react的预设,这样babel就会将React转译为原生的语法。
编写React组件
我们简单的写一个App组件,并在index中引入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import React from 'react'
class App extends React.Component { componentDidMount() { console.log('this is App') }
render() { return ( <div> this is App </div> ) } }
export default App
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import ReactDOM from 'react-dom' import React from 'react' import App from './App.js'
class Index extends React.PureComponent { componentDidMount() { console.log('this is index') }
render() { return ( <div> <App /> </div> ) } } ReactDOM.render(<Index />, document.querySelector('#root'))
if (module.hot) { module.hot.accept() }
|
写过React的都知道,React需要将根组件挂在到Dom上,这个时候我们就还差一步,在模版html中加入:
1 2 3 4 5 6 7 8 9 10 11 12
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="root"></div> </body> </html>
|
运行
配置完后,我们输入npm run dev,查看结果.
骨架屏
这是一个这段时间比较新的概念,他是指在web资源还没加载完成白屏时,展示给用户看的简单图案,这个图案一般都和该web结构差不多,因此称为“骨架屏”:

分析
我们在打包后,查看dist中的index.html:
1 2 3 4 5 6 7 8 9 10 11 12
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <link href="css/main.d3b41950be14d841d949.css" rel="stylesheet"></head> <body> <div id="root"></div> <script type="text/javascript" src="js/bundle.js"></script></body> </html>
|
当我们访问到这个页面的时候,首先加载完html文件,再去加载css文件,最终加载js文件,而html文件是一个空的页面,只有js加载完成后,react的组件才会被注入到html中,所以,我们就能在js注入之前,将原本空的dom加上一些结构和样式,在加载js过程中,就能先给用户看到部分内容,而不是完全白屏。
原始做法
可能我们最先想到的是,在<div id="root"></div>中加入内容,比如<div id="root">loading</div>,没错,这样确实可以,js加载完成后,react将<div id="root">loading</div>替换成业务组件。
- index.html
1 2 3 4 5 6 7 8 9 10 11 12
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="root">Loading...</div> </body> </html>
|
这个时候,我们就初步完成了一个减缩版“骨架屏”,我们来看下效果:

配合Webpack
上面那种方法太不灵活,没法将业务组件和Loading的样式区分开来,这样我们就需要借助Webpack来完成更高级的配置。
我们最早之前为了生成一个html模板的时候,引入了一个插件交html-webpack-plugin,他能够为我们自动生成一个html文件,然后将css和js导入进入,这时,我们在想,是否能够利用他将我们写的loading导入进html模板中。
在webpacl.config.js中配置html导入内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| module.exports = (env, argv) => { const devMode = argv.mode === 'development' const loading = { html: fs.readFileSync(path.join(__dirname, './loading/index.html')), css: `<style>${fs.readFileSync(path.join(__dirname, './loading/index.css'))}</style>`, } return { ... plugins: [ new HtmlWebpackPlugin({ template: './src/index.html', filename: 'index.html', loading, }) ... ], ... } }
|
在根目录下编写loading组件:
1
| <div class="loading"></div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @keyframes donut-spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .loading { border: 4px solid rgba(0, 0, 0, 0.1); border-left-color: #7983ff; border-radius: 50%; width: 30px; height: 30px; animation: donut-spin 1.2s linear infinite; margin: 0 auto; margin-top: 45vh; }
|
将内容导入模板html中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <%= htmlWebpackPlugin.options.loading.css %> <title>Document</title> </head> <body> <div id="root"> <%= htmlWebpackPlugin.options.loading.html %> </div> </body> </html>
|
运行
这样,我们就简单完成了一个类似于“骨架屏”的效果:

当然,真正的骨架屏需要按照项目的布局,来做进一步的优化.
Last
这一章节我们完成了React的配置,并且学会了一个比较有趣的技巧,一个简单的loading能够给为用户带来更好的体验,比较白屏确实让人讨厌透顶~
本章节的代码已经上传到Github,传送门webpack-study,请自行切换到chapter-05分支。